package org.or5e.api.bm;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

import org.or5e.api.bm.BulkMailConfig.ATTRIB_KEY;
import org.or5e.api.bm.server.SMTPServer;
import org.or5e.core.BaseObject;

public final class CampaignThread extends Thread {

    private BulkMailStatus status = new BulkMailStatus((short) 0, (short) 0, (short) 0, (short) 0, (short) 0, null, null, true);
    private ArrayList<SMTPServer> serverList = new ArrayList<SMTPServer>();
    private File goodFile = null;
    private File badFile = null;
    private ServerSelector ss = null;
    private final BulkMailConfig config;
    public final String campaignName;
    private final BaseObject obj;
    private volatile boolean run = true;
    short doneEmailList = 0;

    public CampaignThread(String campaignName, BulkMailConfig config, BaseObject obj) {
        this.config = config;
        this.campaignName = campaignName;
        this.serverList.add(config.getSMTPServer());
        this.obj = obj;
        goodFile = (File) this.config.getAttribute(ATTRIB_KEY.GOODFILE);
        badFile = (File) this.config.getAttribute(ATTRIB_KEY.BADFILE);
    }

    public void run() {
        this.obj.putMessage(campaignName + ": is Started. ");
        setServerSelector(new ServerSelection());
        short checkServer = 0;

        BufferedReader emailReader = null;
        try {
            emailReader = new BufferedReader(new FileReader((File) config.getAttribute(ATTRIB_KEY.GOODFILE)));
            SMTPServer server = null;
            for (String email; (email = emailReader.readLine()) != null && run; doneEmailList++) {
                server = ss.getServer();
                while (server == null) {
                    server = ss.getServer();
                    if (checkServer++ > 3) {
                        break;
                    }
                }
                if (checkServer > 3) {
                    break;
                }
                checkServer = 0;
                server.sendMail("\"Admin\"<admin@sabre.com>", email, "test", "Test Message");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        } finally {
            try {
                if (emailReader != null) {
                    emailReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        this.status.setNoOfCompleted(doneEmailList);
        this.status.setIsRunning(Boolean.FALSE);
        System.out.println(campaignName + ": is Ended. ");
    }

    private class ServerSelection implements ServerSelector {

        private int locatorIndex = 0;

        public SMTPServer getServer() {
            SMTPServer server = null;
            if (serverList.size() > locatorIndex) {
                while (server == null) {
                    server = (SMTPServer) serverList.get(locatorIndex++);
                    if (serverList.size() > locatorIndex) {
                        break;
                    }
                }
            } else {
                locatorIndex = 0;
            }
            return server;
        }
    }

    public synchronized void addServer(SMTPServer server) {
        serverList.add(server);
    }

    public synchronized void removeServer(SMTPServer server) {
        serverList.remove(server);
    }

    public synchronized ArrayList<SMTPServer> getServerList() {
        return serverList;
    }

    public synchronized BulkMailStatus getCampaignStatus() {
        this.status.setNoOfCompleted(doneEmailList);
        return this.status;
    }

    private synchronized void setServerSelector(ServerSelector ss) {
        this.ss = ss;
    }

    public final File getGoodFile() {
        return this.goodFile;
    }

    public final File getBadFile() {
        return this.badFile;
    }

    public void stopThread() {
        this.run = false;
        releaseAndStoreResources();
    }

    private void releaseAndStoreResources() {
    }
}
